home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Sample Code / QuickTime / Show Movie / Sources / MovieStuff.c < prev    next >
Encoding:
Text File  |  1995-11-20  |  30.6 KB  |  984 lines  |  [TEXT/MMCC]

  1.  
  2. /*
  3.   File:            MovieStuff.c
  4.   Contains:         movie handling routines
  5.   Written by:    Jason Hodges-Harris & Don Swatman
  6.   Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  7. */
  8.  
  9. //==============================================
  10. // MovieStuff.c
  11. //
  12. // This handles all the clever movie stuff.
  13. // - Sets up movie windows
  14. // - Tears down movie windows
  15. // - handles updates and events
  16. // - handles slaving, altering playback speed, looping etc
  17. //==============================================
  18.  
  19. #include <Memory.h>
  20. #include <TextUtils.h>
  21. #include <Movies.h>
  22.  
  23. #include "MovieStuff.h"
  24. #include "WindStuff.h"
  25.  
  26. //==============================================
  27. //  CallBackInfoType
  28. //
  29. // This structure is used to store QuickTime 
  30. // call backs and any data they require.
  31. // - It has a several parameters at the front,
  32. //   then a variable size record at the end. It also
  33. //   needs the parameters used in CallMeWhen
  34. // - It's size is:
  35. //      "sizeof(CallBackInfoType) + callBackDataSize - sizeof(long)"
  36. // - Data should not contain the only reference
  37. //   to other handles, as it can't dispose of them
  38. // - It forms a linked list. Any new items are
  39. //   added to the front.
  40. // - It should be passed in the call backs 
  41. //   reference field.
  42. //==============================================
  43.  
  44. struct CallBackInfoType
  45. {
  46.     struct CallBackInfoType **hNextCallBackInfo; // Next in the list
  47.     
  48.     QTCallBack actualCallBack;    // the call back
  49.     WindowPtr  pParentWindow;     // parent window of the movie
  50.     long       param1;            // Used in "CallMeWhen"
  51.     long       param2;            // Used in "CallMeWhen"
  52.     long       param3;            // Used in "CallMeWhen"
  53.     long       callBackDataSize;  // Size of the data attached on the end
  54.     long       callBackDataStart; // where the data starts
  55. };
  56.  
  57. typedef struct CallBackInfoType CallBackInfoType,
  58.     *CallBackInfoPtr, **CallBackInfoHdl;
  59.  
  60. //==============================================
  61. //  DocMovieInfoType
  62. //
  63. // Used to hold information about a movie within
  64. // a window
  65. // - It should be attached to the windows RefCon
  66. //==============================================
  67.  
  68. struct DocMovieInfoType
  69. {
  70.         FSSpec          movieFileSpec;  // movies File Spec
  71.         MovieController movieControls;    // standard movie controller
  72.         Movie           actualMovie;        // the Movie itself!
  73.         Boolean         movieAutoClose; // True if the window closes after movie finishes
  74.         TimeBase              moviesTimeBase;
  75.         TimeScale              moviesTimeScale;
  76.         CallBackInfoHdl hFirstCallBackData; // Handle to first item of the call back info list
  77.         WindowPtr       pSlaveWind;     // WindowPtr of this movies slave
  78. };
  79.  
  80. typedef struct DocMovieInfoType DocMovieInfoType,
  81.     *DocMovieInfoPtr, **DocMovieInfoHndl;
  82.  
  83. //==============================================
  84. // Global Stuff, init and tear down             
  85. //==============================================
  86.  
  87. // Prototypes of functions  used in UPPs
  88. pascal void StartMovieCB(QTCallBack myCallBack,long ref);
  89. pascal void AlterRate( QTCallBack myCallBack,long ref);
  90. pascal void AlterMasterOffset( QTCallBack myCallBack,long ref);
  91.  
  92. // Global UPPs
  93. QTCallBackUPP        gStartMovieCBUpp;
  94. QTCallBackUPP        gAlterRateUpp;
  95. QTCallBackUPP        gAlterMasterOffsetUpp;
  96.  
  97. //----------------------------------------------
  98. // InitMovieGlobals
  99. //
  100. // Init's any globals used in MovieStuff
  101. // i.e. the UPPs             
  102. //----------------------------------------------
  103. void InitMovieGlobals(void)
  104. {
  105.     gStartMovieCBUpp = nil;
  106.     gAlterRateUpp    = nil;
  107.     gAlterMasterOffsetUpp = nil;
  108.  
  109. //    Create routine descriptor for "StartMovieCB" QT callback routine
  110.     gStartMovieCBUpp = NewQTCallBackProc(StartMovieCB);
  111.  
  112. //    Create routine descriptor for "AlterRate" QT callback routine
  113.     gAlterRateUpp = NewQTCallBackProc(AlterRate);
  114.  
  115. //    Create routine descriptor for "AlterMasterOffset" QT callback routine
  116.     gAlterMasterOffsetUpp = NewQTCallBackProc(AlterMasterOffset);
  117.  
  118. }
  119.  
  120. //----------------------------------------------
  121. // KillMovieGlobals
  122. //
  123. // Removes the UPPs             
  124. //----------------------------------------------
  125. void KillMovieGlobals(void)
  126. {
  127. // Clear the Universal Proc Pointers
  128. //    You don't need to do this as quiting the app will do it for you,
  129. //    however, I have this thing about neatness.    
  130.     if (gStartMovieCBUpp)
  131.         DisposeRoutineDescriptor(gStartMovieCBUpp);
  132.     if (gAlterRateUpp)
  133.         DisposeRoutineDescriptor(gAlterRateUpp);
  134.     if (gAlterMasterOffsetUpp)
  135.         DisposeRoutineDescriptor(gAlterMasterOffsetUpp);
  136.         
  137. }
  138.  
  139.  
  140. //==============================================
  141. //
  142. // Error Reporting
  143. //
  144. //==============================================
  145.  
  146. //----------------------------------------------
  147. // Report Error
  148. //
  149. // If an error occurs, Uses DebugStr to send out
  150. // some text passed to it, then the error number
  151. //----------------------------------------------
  152.  
  153. void ReportError( Str255 errText, OSErr theErr );
  154. void ReportError( Str255 errText, OSErr theErr )
  155. {
  156.     Str255 errorStr;
  157.  
  158. // Check there is an error
  159.     if (theErr)
  160.     {
  161. // convert theErr number to text
  162.         NumToString(theErr,errorStr);
  163.  
  164. // if there is error text then displat it
  165.         if (errText != "\p")
  166.             DebugStr(errText);
  167. // Display error number
  168.         DebugStr(errorStr);
  169.     }
  170. }
  171.  
  172. //----------------------------------------------
  173. // GetAndReportError
  174. //
  175. //   Checks GetMoviesError and reports error if
  176. // needed
  177. //----------------------------------------------
  178. OSErr GetAndReportError( Str255 errText );
  179. OSErr GetAndReportError( Str255 errText )
  180. {
  181.     OSErr  theErr;
  182.  
  183.     theErr = GetMoviesError();       // Get Movies error number
  184.     ReportError( errText, theErr );  // And report it
  185.     return(theErr);                  // Oh yeh, return it to the caller
  186. }
  187.  
  188. //==============================================
  189. //
  190. // Call Back info stuff
  191. //
  192. // Following routines handle the CallBackInfoHdl
  193. // structure.
  194. //==============================================
  195.  
  196. //----------------------------------------------
  197. // AddNewCallBackInfo
  198. //
  199. //  Creates a new "CallBackInfoHdl", intialises and
  200. //    returns it
  201. // - It puts "pWindow" and "theCallBack" into the structure
  202. // - It appends "dataSize" bytes of data from "pDataStart"
  203. //   on to the end of the structure 
  204. //----------------------------------------------
  205.  
  206. CallBackInfoHdl AddNewCallBackInfo( WindowPtr  pWindow,
  207.                                                                         QTCallBack theCallBack,
  208.                                                                         Ptr        pDataStart,
  209.                                                                         long       dataSize,
  210.                                                                         long       param1,
  211.                                                                         long       param2,
  212.                                                                         long       param3
  213.                                                                     );
  214. CallBackInfoHdl AddNewCallBackInfo( WindowPtr  pWindow,
  215.                                                                         QTCallBack theCallBack,
  216.                                                                         Ptr        pDataStart,
  217.                                                                         long       dataSize,
  218.                                                                         long       param1,
  219.                                                                         long       param2,
  220.                                                                         long       param3
  221.                                                                     )
  222. {
  223.     CallBackInfoHdl  hNewCBInfo = nil;  // the new call back info record
  224.     DocMovieInfoHndl hDocMovieInfo;
  225.     long newSize;   // Size of hNewCBInfo and the data added to it
  226.     
  227. // Calculate how big the block needs to be
  228.     newSize = sizeof(CallBackInfoType) + dataSize - sizeof(long);
  229.  
  230. // Create the call back data item
  231.     hNewCBInfo = (CallBackInfoHdl) NewHandle (newSize);
  232.  
  233. // Check that we actualy did create it!
  234.     if (hNewCBInfo)
  235.     {
  236.  
  237. // Setup the structure
  238.  
  239.         (**hNewCBInfo).hNextCallBackInfo = nil;
  240.         (**hNewCBInfo).actualCallBack    = theCallBack;
  241.         (**hNewCBInfo).pParentWindow     = pWindow;
  242.         (**hNewCBInfo).param1 = param1;
  243.         (**hNewCBInfo).param2 = param2;
  244.         (**hNewCBInfo).param3 = param3;
  245.         (**hNewCBInfo).callBackDataSize  = 0;
  246.  
  247. // Add in the data (if there is any)
  248.  
  249.         if (dataSize && pDataStart)
  250.         {
  251.             (**hNewCBInfo).callBackDataSize  = dataSize;
  252.             BlockMove( pDataStart, &((**hNewCBInfo).callBackDataStart), dataSize);
  253.         }
  254.  
  255. // Now, link it into the window data structure (attach it to the front of the chain)
  256.  
  257.         hDocMovieInfo = (DocMovieInfoHndl)GetWRefCon ( pWindow );
  258.         (**hNewCBInfo).hNextCallBackInfo     = (**hDocMovieInfo).hFirstCallBackData;
  259.         (**hDocMovieInfo).hFirstCallBackData = hNewCBInfo;
  260.     }
  261.     
  262.     return( hNewCBInfo );
  263. }
  264.  
  265. //----------------------------------------------
  266. //  RemoveCallBackInfo
  267. //
  268. //  Scans down the CallBackInfoHdl chain and disposes
  269. // of each one
  270. //----------------------------------------------
  271.  
  272. void RemoveCallBackInfo ( CallBackInfoHdl hFirstItem );
  273. void RemoveCallBackInfo ( CallBackInfoHdl hFirstItem )
  274. {
  275.     CallBackInfoHdl  hNextCBInfo;
  276.     CallBackInfoHdl  hDisposeData;
  277.  
  278.     if (hFirstItem)
  279.     {
  280. // Scan down the chain of items, disposing as we go
  281.         hNextCBInfo = hFirstItem;
  282.         while (hNextCBInfo)
  283.         {
  284.             hDisposeData = hNextCBInfo;
  285.             hNextCBInfo  = (**hNextCBInfo).hNextCallBackInfo;
  286.     
  287.         // Dispose of the call back
  288.             DisposeCallBack( (**hDisposeData).actualCallBack );
  289.  
  290.         // Dispose of the call back info block
  291.             DisposeHandle( (Handle) hDisposeData);
  292.         }
  293.     }
  294.         
  295. }
  296.  
  297. //----------------------------------------------
  298. //  GetDataFromCBInfo
  299. //
  300. // Extracts the data from a CallBackInfoHdl and
  301. // moves the data into it. Checks the stored structure
  302. // is smaller than requested size. Ideally they should
  303. // be the same size.
  304. //----------------------------------------------
  305.  
  306. Boolean GetDataFromCBInfo ( CallBackInfoHdl  hCallBackInfo,
  307.                                                         Ptr    pData,
  308.                                                         long   maxDataSize   );
  309. Boolean GetDataFromCBInfo ( CallBackInfoHdl  hCallBackInfo,
  310.                                                         Ptr    pData,
  311.                                                         long   maxDataSize   )
  312. {
  313.     Boolean isOk = false;
  314.     
  315. // Check that we have a call back,
  316. //                     and we have some where to put the data,
  317. //                         and it's bigger than 0
  318.     if (hCallBackInfo && pData && maxDataSize)
  319.  
  320. // Check the call back data is smaller than the new structure 
  321.         if ( (**hCallBackInfo).callBackDataSize  <= maxDataSize)
  322.         {
  323.  
  324. // Move the data to pData
  325.             BlockMove ( &((**hCallBackInfo).callBackDataStart),
  326.                                     pData,
  327.                                     (**hCallBackInfo).callBackDataSize );
  328.             isOk = true;
  329.         }
  330.     return ( isOk );
  331. }
  332.  
  333. //----------------------------------------------
  334. //  IsMoviePlaying
  335. //
  336. // Find out if any movie is playing
  337. //----------------------------------------------
  338.  
  339. Boolean IsMoviePlaying (void)
  340. {
  341.     DocMovieInfoHndl hDocMovieInfo; // The movie we're checkings info
  342.     Boolean movieLive = false; // set to true if there is a live window
  343.     short   windCount;
  344.     
  345. // Scan the window list until we've found a live window
  346.     for (windCount = 0;(windCount < kMaxWindows) && !movieLive; windCount++ )
  347. // If this window is open
  348.         if (gTheWinds[windCount])
  349.             {
  350. // Get information about the movie
  351.                 hDocMovieInfo = (DocMovieInfoHndl)GetWRefCon (gTheWinds[windCount]);
  352.  
  353. // Use IsMovieDone to see if it's still running
  354.                 if (!IsMovieDone((**hDocMovieInfo).actualMovie) )
  355.                     movieLive = true;
  356.             }
  357.     return (movieLive);
  358. }
  359.  
  360. //----------------------------------------------
  361. // UpdateMovieWindow
  362. //----------------------------------------------
  363. void UpdateMovieWindow (  WindowPtr pWindow   )
  364. {
  365. // Get the movie from the ref con and update it. Easy.
  366.     UpdateMovie( (**(DocMovieInfoHndl)GetWRefCon( pWindow )).actualMovie);
  367. }
  368.  
  369. //----------------------------------------------
  370. // Load a movie into memory
  371. //
  372. //  Use standard file to get and load a movie
  373. //----------------------------------------------
  374. void    LoadOneMovie( DocMovieInfoHndl hDocMovieInfo );
  375. void    LoadOneMovie( DocMovieInfoHndl hDocMovieInfo )
  376. {
  377.     Movie         myNewMovie = nil;   // The new movie
  378.     StandardFileReply    newMovieFile;   // Standard File Reply about the  movies file
  379.     Str255        myMovieName;        // The Movies name
  380.     OSErr         error;
  381.     SFTypeList    myTypes = {MovieFileType}; // File types we want Standard File to get
  382.     short         myMovieResFile;     // Movie files ref number
  383.     short         myMovieResID = 0;   // Load the first movie res
  384.     Boolean       movieChanged;       // Set to true if movie was changed durring 
  385.                                                                         // loading to resolve references
  386.         
  387. // Use standard file to get the fsSpec etc.
  388.     StandardGetFilePreview(nil,1,myTypes,&newMovieFile);
  389.     if (newMovieFile.sfGood)
  390.     {
  391. // Open the movie file
  392.         error = OpenMovieFile( &newMovieFile.sfFile, &myMovieResFile, fsRdPerm);
  393.         if (error==noErr)
  394.         {
  395. // Store the file spec
  396.             (**hDocMovieInfo).movieFileSpec = newMovieFile.sfFile;
  397.  
  398. // Move Movie data in to memory
  399.             error = NewMovieFromFile( &myNewMovie, myMovieResFile, &myMovieResID,
  400.                                       myMovieName, newMovieActive, &movieChanged);
  401.  
  402. // Close the file as we succeded in opening it
  403.             CloseMovieFile (myMovieResFile);
  404.         }
  405.     }
  406.     (**hDocMovieInfo).actualMovie =    myNewMovie; // Return myNewMovie
  407. }
  408.  
  409. //----------------------------------------------
  410. // ServiceMovieTasks
  411. //
  412. // Used to Handle the null event. You need to handle
  413. // this to make the movie play!
  414. // - First it sees if the movie controller has an event
  415. // - Scans the window list looking for movies
  416. // - If the movie has finished then close it if the
  417. //   flags are set that way
  418. // - If any movies are active, then call MoviesTask
  419. //   to make them play
  420. // - Finally return true if the event was handled by the
  421. //   movie controller
  422. //----------------------------------------------
  423. Boolean ServiceMovieTasks ( WindowPtr pWindow, const EventRecord *theEvent )
  424. {
  425. #pragma unused ( pWindow )
  426.  
  427.     Boolean doneProccessing = false;  // goes to true if MCIsPlayerEvent handles event
  428.     DocMovieInfoHndl hDocMovieInfo;   // Current windows movie info
  429.     short   windCount;
  430.     Boolean needMovieTasks = false;   // Goes true if there is a movie running
  431.     Boolean moviePlaying;
  432.     
  433. // Scan window list
  434.     for (windCount = 0;windCount < kMaxWindows; windCount++ )
  435.         if (gTheWinds[windCount])
  436.             {
  437. // Get movie information for this window
  438.                 hDocMovieInfo = (DocMovieInfoHndl)GetWRefCon (gTheWinds[windCount]);
  439.  
  440. // Handle any events to this windows movie controller if it's got one
  441.                 if (!doneProccessing)
  442.                     if ((**hDocMovieInfo).movieControls)
  443.                         if (MCIsPlayerEvent((**hDocMovieInfo).movieControls, theEvent))
  444.                             doneProccessing = true;
  445.     
  446. // Next bit checks to see if a window has finished playing (by using
  447. // IsMovieDone) and closes it if auto close has been set for it
  448.                 moviePlaying = !IsMovieDone((**hDocMovieInfo).actualMovie);
  449.                 if (   (**hDocMovieInfo).movieAutoClose && (!moviePlaying) )
  450.                     CloseOurWindow( windCount );
  451.                 else
  452.                     if (moviePlaying)
  453.                         needMovieTasks = true; // Hey there's a movie running
  454.             }
  455.  
  456. // If we have an active movie, then service all movies
  457.     if (needMovieTasks)
  458.         MoviesTask(nil,0);
  459.  
  460.     return ( doneProccessing );    
  461. }
  462.  
  463. //----------------------------------------------
  464. //  CloseMovieWindow
  465. //
  466. // Close a movie window and destroys associated
  467. // structures. If this is a Master window,
  468. // sets "*pSlaveWindow" to the slave WindowPtr
  469. //----------------------------------------------
  470. OSErr CloseMovieWindow( WindowPtr pWindow,
  471.                                                 WindowPtr *pSlaveWindow )
  472. {
  473.     DocMovieInfoHndl hDocMovieInfo;
  474.     
  475.     *pSlaveWindow = nil;
  476.  
  477. // Get movie structure
  478.     hDocMovieInfo = (DocMovieInfoHndl)GetWRefCon(pWindow);
  479.  
  480.     if (hDocMovieInfo)
  481.     {
  482. // Set the slave WindowPtr
  483.         *pSlaveWindow = (**hDocMovieInfo).pSlaveWind;
  484.  
  485. // dispose movie
  486.         DisposeMovie((**hDocMovieInfo).actualMovie);
  487.     
  488. // dispose of the controller if it exists
  489.         if ((**hDocMovieInfo).movieControls)
  490.             DisposeMovieController ( (**hDocMovieInfo).movieControls );
  491.     
  492. // dispose of call back structures
  493.         RemoveCallBackInfo ( (**hDocMovieInfo).hFirstCallBackData );
  494.         
  495. // dispose movie structure
  496.         DisposeHandle( (Handle)hDocMovieInfo );
  497.     }
  498.     return ( noErr );
  499. }
  500.  
  501. //----------------------------------------------
  502. //   OpenMovieWindow
  503. //
  504. // - Opens a movie
  505. // - Creates and initialises the windows movie
  506. //   structure "DocMovieInfoHndl"
  507. // - Creates (if wanted) a movie controller
  508. // - Sizes the window to fit the movie and controller
  509. // - Shows the window
  510. //----------------------------------------------
  511. OSErr OpenMovieWindow ( WindowPtr pWindow,
  512.                                                 Boolean   doesAutoClose,
  513.                                                 Boolean   hasControler  )
  514. {
  515.     OSErr theErr = noErr;
  516.     DocMovieInfoHndl hDocMovieInfo = nil; // new window movie information
  517.     Rect moviesRect;   // Size of the movie
  518.     Rect newWindRect;  // New Windows rect (movie + Controllers rect)
  519.     
  520.     if (!pWindow)
  521.     {  // Error !!!!
  522.         DebugStr("\pHey, this window doesn't exists!!");
  523.         theErr = userCanceledErr;  // Should be something more appropriate
  524.     }
  525.     else
  526.     {
  527.  
  528. // allocate new movie doc structure
  529.         hDocMovieInfo = (DocMovieInfoType**) NewHandle (sizeof(DocMovieInfoType));
  530.         if (hDocMovieInfo == nil)
  531.         { // Error !!!!
  532.             DebugStr("\pError allocating doc handle");
  533.             theErr = userCanceledErr;  // Should be something more appropriate
  534.         }
  535.         else
  536.         {
  537. // Set up the hDocMovieInfo record
  538.             (**hDocMovieInfo).movieAutoClose = doesAutoClose;
  539.             (**hDocMovieInfo).hFirstCallBackData  = nil;
  540.             (**hDocMovieInfo).movieControls = nil;
  541.             (**hDocMovieInfo).actualMovie   = nil;
  542.             (**hDocMovieInfo).pSlaveWind    = nil;
  543.             
  544. // set window refcon to movie doc handle
  545.             SetWRefCon( pWindow, (long)hDocMovieInfo );
  546.             SetPort(pWindow);
  547.                     
  548. // load movie refs into doc structure
  549.             LoadOneMovie ( hDocMovieInfo );
  550.             if ((**hDocMovieInfo).actualMovie == nil)
  551.             { // Cancel button pressed or Error !!!!
  552.                 theErr = userCanceledErr;  // Should be something more appropriate
  553.                 return(theErr);
  554.             }
  555.             else
  556.             {
  557. // get timebase from movie
  558.                 (**hDocMovieInfo).moviesTimeBase = GetMovieTimeBase((**hDocMovieInfo).actualMovie);
  559.                 theErr = GetAndReportError( "\pError!! GetMovieTimeBase");
  560.  
  561. // get timescale from movie
  562.                 if (!theErr)
  563.                 {
  564.                     (**hDocMovieInfo).moviesTimeScale = GetMovieTimeScale((**hDocMovieInfo).actualMovie);
  565.                     theErr = GetAndReportError( "\pError!! Getting movie time scale");
  566.                 }
  567.  
  568.                 if (!theErr)
  569.                     if (!hasControler)
  570.                     {
  571.     // Don't want a controller, so just
  572.         // Get movies rect as this is the size of the window
  573.                         GetMovieBox((**hDocMovieInfo).actualMovie, &newWindRect);
  574.                     }
  575.                     else
  576.                     {
  577.     // We want a movie controller so create it beneath the movie
  578.         // Get the movies rect as this is the size we want to put it in
  579.                         GetMovieBox((**hDocMovieInfo).actualMovie, &moviesRect);
  580.     
  581.         //Create a controller and put below the movie. as moviesRect is the size of the movie,
  582.         // the controller will fall outside the rect
  583.                         (**hDocMovieInfo).movieControls = NewMovieController ( (**hDocMovieInfo).actualMovie,
  584.                                                                                                                                      &moviesRect,
  585.                                                                                                                                      mcTopLeftMovie);
  586.                         if ((**hDocMovieInfo).movieControls == nil)
  587.                         { // Failed to create controller Error !!!!
  588.                             theErr = userCanceledErr;  // Should be something more appropriate
  589.                             return(theErr);
  590.                         }
  591.                         else
  592.                         {
  593.     // Get movieControllers rect. Because it is attached the movie, it will return
  594.     // the controller and movies size
  595.                             theErr = MCGetControllerBoundsRect((**hDocMovieInfo).movieControls, &newWindRect);
  596.                         }
  597.                     }
  598.  
  599.                 if (!theErr)
  600.                 {
  601.     // Size the window to fit the movie and controller
  602.                     SizeWindow( pWindow,newWindRect.right, newWindRect.bottom,true);
  603.                 }
  604.             }
  605.         }
  606.     }
  607.     
  608.     return ( theErr );
  609. }
  610.  
  611. //==============================================
  612. // The time base call back procs
  613. //==============================================
  614.  
  615. //----------------------------------------------
  616. //   AlterMasterOffset
  617. //
  618. // QuickTime callback used to set the SetTimeBaseValue.
  619. // - Can be used to make the movie loop.
  620. // - Takes a value in seconds in the data of
  621. //   the CallBackInfoHdl passed in "ref"
  622. //----------------------------------------------
  623.  
  624. pascal void AlterMasterOffset(QTCallBack myCallBack,long ref)
  625. {
  626.     DocMovieInfoHndl hDocMovieInfo;
  627.     WindowPtr pWindow;
  628.     TimeValue newTimeValue; // Where we want to move to
  629.     OSErr     theErr;
  630.  
  631. // Extract where we want to move to from (CallBackInfoHdl)ref
  632.     if (GetDataFromCBInfo( ( CallBackInfoHdl)ref,
  633.                                                  (Ptr) &newTimeValue, sizeof ( TimeValue ) ))
  634.     {
  635.         pWindow = (**(CallBackInfoHdl)ref).pParentWindow;  // Get the parent window
  636.         hDocMovieInfo = (DocMovieInfoHndl)GetWRefCon ( pWindow ); // Get the movie info
  637. // Move our position in the movie
  638.         SetTimeBaseValue ( (**hDocMovieInfo).moviesTimeBase,
  639.                                              newTimeValue,
  640.                                              (**hDocMovieInfo).moviesTimeScale);
  641. // Finally must reschedule the call back so that it happens again
  642.         theErr = CallMeWhen ( myCallBack,
  643.                                                     gAlterMasterOffsetUpp, ref,
  644.                                                     (**(CallBackInfoHdl)ref).param1,
  645.                                                     (**(CallBackInfoHdl)ref).param2,
  646.                                                     (**(CallBackInfoHdl)ref).param3);
  647.     }
  648. }
  649.  
  650. //----------------------------------------------
  651. //   AlterRate
  652. //
  653. // QuickTime callback used to set the movies rate.
  654. // - Alters the speed of playback.
  655. // - Takes a value in the data of the CallBackInfoHdl
  656. //   passed in "ref"
  657. //----------------------------------------------
  658.  
  659. pascal void AlterRate( QTCallBack myCallBack,long ref)
  660. {
  661. #pragma unused ( myCallBack )
  662.  
  663.     DocMovieInfoHndl hDocMovieInfo;
  664.     WindowPtr pWindow;
  665.     long      newMovieRate;
  666.  
  667. // Extract the new speed we want the movie to run at
  668.     if (GetDataFromCBInfo ( ( CallBackInfoHdl)ref, (Ptr) &newMovieRate, sizeof ( long ) ))
  669.     {
  670.         pWindow = (**(CallBackInfoHdl)ref).pParentWindow;  // Get the parent window
  671.         hDocMovieInfo = (DocMovieInfoHndl)GetWRefCon ( pWindow ); // Get the movie info
  672.  
  673.  
  674. // Change the movies rate
  675.         SetMovieRate((**hDocMovieInfo).actualMovie, newMovieRate);
  676.     }
  677.  
  678.     return;
  679. }
  680.  
  681. //----------------------------------------------
  682. //   StartMovieCB
  683. //
  684. // QuickTime callback used to start a movie.
  685. // - Takes a value (Movie) in the data of the CallBackInfoHdl
  686. //   passed in "ref" which is the movie you want to start.
  687. //----------------------------------------------
  688.  
  689.  
  690. pascal void StartMovieCB(QTCallBack myCallBack,long ref)
  691. {
  692. #pragma unused ( myCallBack )
  693.  
  694.     Movie movieToStart;
  695.         
  696.     if (GetDataFromCBInfo ( ( CallBackInfoHdl)ref, (Ptr) &movieToStart, sizeof ( Movie ) ))
  697.     {
  698.         SetMovieRate(movieToStart,65536);
  699.     }
  700. }
  701.  
  702. //==============================================
  703. // Set up the various options
  704. //==============================================
  705.  
  706. //----------------------------------------------
  707. // SetupMovieRate
  708. //
  709. // - Sets up the call backs to change the play back speed
  710. //   of the movie.
  711. // - "delayBeforeChange" gives the time in seconds when
  712. //   the first speed change happens or a constant that
  713. //   tells it to change at 1/3 (& 2/3) of the movies 
  714. //   duration.
  715. //----------------------------------------------
  716.  
  717. OSErr SetupMovieRate( WindowPtr pWindow,  short delayBeforeChange  )
  718. {
  719.     OSErr            theErr = noErr;
  720.     QTCallBack             theNewCallBack;     // Call Back
  721.     long                     theCallBackOffset;  // When we want to change the rate
  722.     TimeValue               theMovieLen;        // Length of the movie
  723.     DocMovieInfoHndl hDocMovieInfo;      // Info about the windows movie
  724.     CallBackInfoHdl  hTempCallBackInfo;  // Call back information
  725.     long             newMovieRate;       // What the new rate will be
  726.  
  727.     hDocMovieInfo = (DocMovieInfoHndl)GetWRefCon (pWindow);
  728.     if (hDocMovieInfo != nil)
  729.     {
  730. // Set up the time base value
  731.         SetTimeBaseValue( (**hDocMovieInfo).moviesTimeBase,
  732.                                             0,
  733.                                             (**hDocMovieInfo).moviesTimeScale);
  734.  
  735.         
  736. // If we're changing by a thirds, we need the movie's length
  737.         if (delayBeforeChange == kOneThird)
  738.             theMovieLen  = GetMovieDuration((**hDocMovieInfo).actualMovie);
  739.  
  740. // ---- First call back - slow playback rate to x2 normal -----
  741.  
  742. // Work out length of delay before callbacks start
  743.         if (delayBeforeChange == kOneThird)
  744.             theCallBackOffset = theMovieLen*0.3333;
  745.         else
  746.             theCallBackOffset = delayBeforeChange * (**hDocMovieInfo).moviesTimeScale;
  747.  
  748. // Create a new call back
  749.         theNewCallBack = NewCallBack((**hDocMovieInfo).moviesTimeBase,callBackAtTime);
  750.  
  751.         newMovieRate = 131072;        // speed up rate to x2 normal
  752.  
  753. // Put the call back into call back chain ( and append newMovieRate )
  754.         hTempCallBackInfo = AddNewCallBackInfo( pWindow,
  755.                                                                                         theNewCallBack,
  756.                                                                                         (Ptr)&newMovieRate, sizeof ( long ),
  757.                                                                                         triggerTimeFwd,
  758.                                                                                         theCallBackOffset,
  759.                                                                                         (**hDocMovieInfo).moviesTimeScale  );
  760.  
  761. // Attach the call back to the movie's time structures
  762.         theErr = CallMeWhen ( theNewCallBack,
  763.                                                         gAlterRateUpp,
  764.                                                         (long)hTempCallBackInfo,
  765.                                                         (**hTempCallBackInfo).param1,
  766.                                                         (**hTempCallBackInfo).param2,
  767.                                                         (**hTempCallBackInfo).param3 );
  768.         if (theErr)
  769.             ReportError( "\pError !! CallMeWhen", theErr );
  770.         else
  771.         {
  772.  
  773. // ---  Second call back - slow playback rate to 1/2 normal ----
  774.  
  775. // Work out length of delay before callbacks start
  776.             if (delayBeforeChange == kOneThird)
  777.                 theCallBackOffset = theMovieLen*0.6666;
  778.             else
  779.                 theCallBackOffset = (2 * delayBeforeChange) * (**hDocMovieInfo).moviesTimeScale;
  780.     
  781. // Create a new call back
  782.             theNewCallBack = NewCallBack((**hDocMovieInfo).moviesTimeBase,callBackAtTime);
  783.     
  784.             newMovieRate = 32768;        // speed up rate to 1/2 normal        
  785.  
  786. // Put the call back into call back chain ( and append newMovieRate )
  787.             hTempCallBackInfo = AddNewCallBackInfo( pWindow,
  788.                                                                                             theNewCallBack,
  789.                                                                                             (Ptr)&newMovieRate, sizeof ( long ),
  790.                                                                                             triggerTimeFwd,
  791.                                                                                             theCallBackOffset,
  792.                                                                                             (**hDocMovieInfo).moviesTimeScale  );
  793.     
  794. // Attach the call back to the movie's time structures
  795.             theErr = CallMeWhen ( theNewCallBack,
  796.                                                         gAlterRateUpp,
  797.                                                         (long)hTempCallBackInfo,
  798.                                                         (**hTempCallBackInfo).param1,
  799.                                                         (**hTempCallBackInfo).param2,
  800.                                                         (**hTempCallBackInfo).param3 );
  801.             if (theErr)
  802.                 ReportError( "\pError !! CallMeWhen", theErr );
  803.         }
  804.     }
  805.     return ( theErr );    
  806. }
  807.  
  808. //----------------------------------------------
  809. //  SetupLoop
  810. //
  811. // Set up a loop in the movie.
  812. // - It uses call backs, to change the position of
  813. //   the movie "loopWhen" seconds into it and moves it
  814. //   to "loopTo" seconds
  815. //----------------------------------------------
  816.  
  817. OSErr SetupLoop ( WindowPtr pWindow,
  818.                                     short    loopWhen,
  819.                                     short    loopTo  )
  820. {
  821.     OSErr  theErr = noErr;
  822.     DocMovieInfoHndl hDocMovieInfo; // Info about the windows movie
  823.     long                 callBackWhen;  // When we want to start loop
  824.     CallBackInfoHdl  hTempCallBackInfo; // Call back information
  825.     QTCallBack             tempCallBack;  // Call Back
  826.     TimeValue        newTimeValue;  // Where we want to loop to
  827.  
  828.     hDocMovieInfo = (DocMovieInfoHndl)GetWRefCon (pWindow);
  829.  
  830. // Calculate when the movie should 'jump'
  831.     callBackWhen = loopWhen*(**hDocMovieInfo).moviesTimeScale;
  832.  
  833. // Creates a call back
  834.     tempCallBack = NewCallBack((**hDocMovieInfo).moviesTimeBase, callBackAtTime);
  835.  
  836. // Set up where it's going to loop to
  837.     newTimeValue = loopTo * (**hDocMovieInfo).moviesTimeScale;
  838.  
  839. // Add the call back to the call back list
  840.     hTempCallBackInfo = AddNewCallBackInfo( pWindow,
  841.                                                                                     tempCallBack,
  842.                                                                                     (Ptr) &newTimeValue, sizeof ( TimeValue ),
  843.                                                                                     triggerTimeFwd,
  844.                                                                                     callBackWhen,
  845.                                                                                     (**hDocMovieInfo).moviesTimeScale  );
  846.  
  847. // Attach the call back to the movie's time structures
  848.     theErr = CallMeWhen( tempCallBack,
  849.                                              gAlterMasterOffsetUpp, (long)hTempCallBackInfo,
  850.                                             (**hTempCallBackInfo).param1,
  851.                                             (**hTempCallBackInfo).param2,
  852.                                             (**hTempCallBackInfo).param3 );
  853.  
  854.     return ( theErr );
  855. }
  856.  
  857. //----------------------------------------------
  858. // SetupSlaveMovie
  859. //
  860. // This sets up the slaved movie
  861. // - "slaveAheadBy" sets the duration that the
  862. //   slave  will lead the master (in seconds)
  863. // - "slaveDelayStart" sets the duration that the
  864. //   slave start will be delayed after the master starts
  865. // - If both values are set the same, the slave will start
  866. //   n seconds behind the master and run in sync
  867. //----------------------------------------------
  868.  
  869.  
  870. OSErr SetupSlaveMovie ( WindowPtr pMasterWindow,
  871.                                                 WindowPtr pSlaveWindow,
  872.                                                 short     slaveAheadBy,
  873.                                                 short     slaveDelayStart )
  874. {
  875.     OSErr                     theErr = noErr;
  876.     DocMovieInfoHndl hDocMasterInfo;  // masters info
  877.     DocMovieInfoHndl hDocSlaveInfo;   // slaves info
  878.     long             slaveTimeOffset; // difference between the two movies
  879.     long                 slaveStartDelay; // when we've got to start the slave
  880.     CallBackInfoHdl  hTempCallBackInfo; // Call back information
  881.     QTCallBack             tempCallBack;    // call back
  882.     Movie            movieToStart;    // Put into the call back
  883.     TimeValue               theMovieLen;     // Length of the movie
  884.  
  885. // Get the info about the two movies
  886.     hDocMasterInfo = (DocMovieInfoHndl)GetWRefCon (pMasterWindow);
  887.     hDocSlaveInfo  = (DocMovieInfoHndl)GetWRefCon (pSlaveWindow);
  888.  
  889. // Attach the slave window onto the master
  890.     (**hDocMasterInfo).pSlaveWind = pSlaveWindow;
  891.  
  892. // Set the master movies time base value
  893.     SetTimeBaseValue((**hDocMasterInfo).moviesTimeBase,0,(**hDocMasterInfo).moviesTimeScale);
  894.  
  895. // slave second movie to first
  896.     SetMovieMasterTimeBase( (**hDocSlaveInfo).actualMovie,
  897.                                                     (**hDocMasterInfo).moviesTimeBase,
  898.                                                     nil );
  899.  
  900. // --- Setup the slave so it will lead the master ---
  901.     if (slaveAheadBy != kInSync)
  902.     {
  903. // Calculate how big the offset should be
  904.         if (slaveAheadBy == kOneThird)
  905.         {
  906.     // get the movie's length
  907.             theMovieLen  = GetMovieDuration((**hDocSlaveInfo).actualMovie);
  908.             slaveTimeOffset  = theMovieLen*0.3333;
  909.         }
  910.         else
  911.             slaveTimeOffset  = slaveAheadBy*(**hDocMasterInfo).moviesTimeScale;
  912.             
  913. // Set the slaves time base offset
  914.         SetTimeBaseValue( (**hDocSlaveInfo).moviesTimeBase,
  915.                                             slaveTimeOffset,
  916.                                             (**hDocSlaveInfo).moviesTimeScale);
  917.         theErr = GetAndReportError( "\pError !! - Offsetting timebase" );
  918.     }
  919.  
  920. // --- Put in the call back to start the slave movie (delayed if requested )--
  921.  
  922. // Set up slaveStartDelay
  923.     if (slaveDelayStart == kInSync)
  924.         slaveStartDelay = 0;
  925.     else
  926.         if (slaveDelayStart == kOneThird)
  927.         {
  928.     // get the movie's length
  929.             theMovieLen  = GetMovieDuration((**hDocMasterInfo).actualMovie);
  930.             slaveStartDelay = theMovieLen*0.3333;
  931.         }
  932.         else
  933.             slaveStartDelay = slaveDelayStart * (**hDocMasterInfo).moviesTimeScale;
  934.  
  935. // Create a new call back
  936.     tempCallBack = NewCallBack((**hDocMasterInfo).moviesTimeBase,callBackAtTime);
  937.  
  938. // Link the call back into the chain
  939.     movieToStart = (**hDocSlaveInfo).actualMovie;
  940.     hTempCallBackInfo = AddNewCallBackInfo( pMasterWindow,
  941.                                                                                     tempCallBack,
  942.                                                                                     (Ptr) &movieToStart, sizeof(Movie),
  943.                                                                                     triggerTimeFwd,
  944.                                                                                     slaveStartDelay,
  945.                                                                                     (**hDocMasterInfo).moviesTimeScale  );
  946.  
  947. // Attach the call back to the movie's time structures
  948.     theErr = CallMeWhen ( tempCallBack, gStartMovieCBUpp,
  949.                                                 (long)hTempCallBackInfo,
  950.                                                 (**hTempCallBackInfo).param1,
  951.                                                 (**hTempCallBackInfo).param2,
  952.                                                 (**hTempCallBackInfo).param3 );
  953.  
  954.     ReportError( "\pError!! - Creating movie start call back", theErr );
  955.  
  956.     return ( theErr );    
  957. }
  958.  
  959.  
  960. //----------------------------------------------
  961. // StartMovieWindow
  962. //
  963. // Start a movie in pWindow
  964. //----------------------------------------------
  965. OSErr StartMovieWindow( WindowPtr pWindow,
  966.                                                 Boolean   fromBegining  )
  967. {
  968.     DocMovieInfoHndl hDocMovieInfo;
  969.     
  970.     if (pWindow)
  971.     {
  972.         hDocMovieInfo = (DocMovieInfoHndl)GetWRefCon (pWindow);
  973.  
  974. // Set up the movie and start it
  975.         if (fromBegining)
  976.             GoToBeginningOfMovie((**hDocMovieInfo).actualMovie);
  977.  
  978.         SetMovieActive((**hDocMovieInfo).actualMovie,true);
  979.         StartMovie((**hDocMovieInfo).actualMovie);
  980.     }
  981.     return( noErr );
  982. }
  983.  
  984.